在有限的時間中,要學會一個前端框架不容易,也沒有一個框架是萬能的,但總要有個開始,筆者在進幾年一直在 extjs 的世界打滾,已有三四年的經驗,最近負責的專案除了使用 extjs,後端使用 grails,發現好處多多,就開發過程中的經驗與大家分享,從實際的例子還有兩個框架遇到得整合問題一一介紹
在 web appication 的開發中,常常會使用到的 form 表單的送出,在 extjs 中我們可以很輕易的使用 Ext.form.Panel
,來完成表單的建立。
可參考 extjs form sample 所提供的範例,來了解程式的運作。
為了簡化表單送出的開發,盡量使用 extjs 所提供的 submit()
來進行表單的送出,他的好處是不需把 form 的欄位收集起來成為 json 往後傳,透過該函式 extjs 會自動將表單所屬元件所定義的 id 作為 request 中的 form data 往後傳,如此一來,一旦表單的內容有所改變,我們也不需調整。
而在筆者目前開發的專案中使用 extjs + grails 的組合並且前後端整合使用 rest 的方式來做為前後端的溝通協定。如下面網址的說明:grails rest,根據文章中建議的 http method 所對應的不同方法來進行資料的增修改查。
不料在過程中,當要進行 PUT 對應的 UPDATE 時,發生 grails 無法解析表單資料的情形,拜一下 google 找到下面資料:
HTTP request params in a PUT never reach the controller
節錄裡面的重點:
It's possible that the servlet container will not parse PUT data as if
it's POST data. I assume that if you use the URL:
http://localhost:8080/app/api/users?userId=5
then "userId" will appear in the "params" object. However, Grails
handles the parsing of XML and JSON requests, so it you were to send
your parameters as XML, they would probably appear in the "params"
instance.
也就是說,在 http method 使用 put 要可以在 grails 中的 params 存取相關的標單資料,必須使用網址方式來傳遞,但若這麼做,就失去我們使用 extjs form 所提供 submit() 的好處,還有資料內容將會輕易的被讀取,更重要的誰也不希望多寫幾行程式,為了要解決此問題,在開始說明解法前我們必須必須了解 http method 中 POST 與 GET 的差異。
一般而言,POST 是用於將表單內的資料送出,PUT 透過 JSON 或是 XML 來將表單送出,也因此後端 server 在接到 request 的 http request method 為 PUT 時,就算有參數包在 request body(form data) grails 也不會進行解析。
了解了表單送出的概念以及在 PUT 的情形下正確的表單資料送出的方式,我們就必須讓 extjs form 在表單送出時,將表單內容轉換為 json,在搜尋 extjs 的 api 總算讓我找到解法,Ext.form.Basic cfg jsonSubmit 就有此參數,一旦設定為 true,當 from 透過函式 submit() 將表單內容送出就會轉換為 json 格式,並且 content-type 變為 application/json。
最後我們只要在 grails 中的 urlMapping.groovy 中,針對你要送出的 route 加上,parseRequest: true
,如下
"/$controller/$action?/$id?"(**parseRequest: true**) {...}
如此就可以解決在 form submit 並且 http method 為 PUT 時,grails 無法將 form 送出的表單資料進行存取的問題。
此問題與我的夥伴 lyhcode 共同發現並解決,也可以參考由他所撰寫詳盡的說明 Ext JS + Grails RESTful Web Services 實作問題之 PUT 表單資料
最後需要在補充說明,上述解法在 grails 2.2.4 之前有效,但在 2013/9/9 release 的 grails 2.3.0 是沒辦法處理的,主要是 parseRequest 在新版已經沒有作用,相關討論可參考下面連結:
文章內有提到使用
user.twitter = request.JSON.twitter
透過上述的方式去存取作為 payload 傳入的 json,但這樣就失去 grails 自動將 params 裡的參數 mapping 為 domain object 的好處,建議可以改為 action url 來區別呼叫的函式如:
* '/item/update':更新
* '/item/create':建立
* '/item/delete':刪除
* '/item/index':查詢
來 mapping 後端對應的函式,需要注意的是原本在 extjs 的 form 屬性 jsonSubmit 設為 false 並且 httpMethod 設為 POST,如此一來在 grails 2.3.0 搭配 extjs 就可以正常運作,迎接新版 grails 的 feature
Ext JS 教學內容由思創軟體提供,共同作者 @lyhcode 與 @smlsun 目前在校園及企業從事 JavaScript(含 Node.js, Ext JS)與 Java(含 Groovy, Grails, Gradle) 教育訓練及顧問工作。